/************************************************************************

							Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  							   memory_buffer.h

	$Header: /resource_editor/memory_buffer.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( MEMORY_BUFFER_H_INCLUDED )
#define MEMORY_BUFFER_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#pragma warning( disable: 4786 )

#include <list>
#include <streambuf>
#include <string>

#include "counted_ptr.h"

/////////////////////////////////////////////////////////////////////////////
// NOTE : this class overloads the steambuff but doesnt impelement the full set of 
// steambuf funtionaity. It doesnt do random seek between buffer segements. It only supports
// linear read / writes between segemetns. It can support random access if you use the merge_buffers_for_read();
// which will compact the segements into one large buffer which then can be randomly seeked within.

/////////////////////////////////////////////////////////////////////////////
// stream buf related class, which like stringbuffer goes to memory, which
// uses efficient allocation of buffers

class t_memory_buffer : public std::streambuf
{
public:
	// Constructor
	t_memory_buffer( );
	t_memory_buffer( int request_mem_size );
	t_memory_buffer( t_memory_buffer * copy_buffer );

	virtual ~t_memory_buffer();

	void				clear_buffer();
	void				compact();
	std::string			copy_buffer();
	
	void				dump_memory( std::streambuf& buffer ) const ;

	void				merge_buffers_for_read();

	virtual bool		read( std::streambuf& buffer );
	void				reset_for_read();
	void				resize_working_buffer( int request_mem_size );
	int					size();
	virtual bool		write( std::streambuf& buffer ) const ;
	
	virtual pos_type	seekoff(off_type offset, std::ios_base::seekdir base_offset,
								std::ios_base::openmode which = std::ios_base::in );
	
	virtual pos_type	seekpos(pos_type position,
								std::ios_base::openmode which = std::ios_base::in );
protected:
	
	void flush_buffer();

	// Virtual overrides
	virtual int			sync( );
	virtual int_type	overflow( int_type c );
	virtual int_type	underflow( );

	void				reset_get_stream_ptrs( int size );
	void				reset_put_stream_ptrs( );

	std::string								m_buffer;
	std::string								m_buffer_read;
	std::list<std::string>					m_buffers;
	int										m_buffer_size_default;
	std::list<std::string>::const_iterator	m_current_block;
	bool									m_is_merged;

};

//counted version used for dynamicly created memory_buffers.
class t_memory_buffer_counted;

typedef t_counted_ptr<t_memory_buffer_counted> t_memory_buffer_counted_ptr;

class t_memory_buffer_counted : public t_memory_buffer , public t_counted_object
{
public:
	// Constructor
	t_memory_buffer_counted( );
	t_memory_buffer_counted( int request_mem_size );
	
	t_memory_buffer_counted_ptr clone();

	virtual ~t_memory_buffer_counted();
};


#endif // MEMORY_BUFFER_H_INCLUDED